/*
 * ArrowWire.js
 *
 * Purpose:
 *
 * Description:
 *
 * History: 2010/10/6, Created by TonyQ
 *
 * Copyright (C) 2010 Potix Corporation. All Rights Reserved.
 */
/**
 * modified from http://github.com/neyric/wireit/blob/v0.6.0a/js/ArrowWire.js
 * commit  c9b903abad6bb62140ae
 *
 * The arrow drawmethod .
 * Every draw method should implements
 * draw: function(drawer,p1,p2,opt) {}
 */


zkex.wire.Drawmethod.arrow = {
    /**
     * Drawing methods for arrows
     */
    draw: function(drawer,p1,p2,opt) { //potix tonyq
        var d = 7; // arrow width/2
        var redim = d + 3; //we have to make the canvas a little bigger because of arrows
        var margin = [4 + redim, 4 + redim];

        // Get the positions of the terminals
        //var p1 = this.terminal1.getXY();
        //var p2 = this.terminal2.getXY();

        var distance = Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2));

        var min = [Math.min(p1[0], p2[0]) - margin[0], Math.min(p1[1], p2[1]) - margin[1]];
        var max = [Math.max(p1[0], p2[0]) + margin[0], Math.max(p1[1], p2[1]) + margin[1]];

        // Store the min, max positions to display the label later
        //this.min = min;
        //this.max = max;

        // Redimensionnement du canvas

        var lw = Math.abs(max[0] - min[0]) + redim;
        var lh = Math.abs(max[1] - min[1]) + redim;

        p1[0] = p1[0] - min[0];
        p1[1] = p1[1] - min[1];
        p2[0] = p2[0] - min[0];
        p2[1] = p2[1] - min[1];

        drawer.SetCanvasRegion(min[0], min[1], lw, lh);

        var ctxt = drawer.getContext();

        // Draw the border
        ctxt.lineCap = opt.bordercap;
        ctxt.strokeStyle = opt.bordercolor;
        ctxt.lineWidth = opt.width + opt.borderwidth * 2;
        ctxt.beginPath();
        ctxt.moveTo(p1[0], p1[1]);
        ctxt.lineTo(p2[0], p2[1]);
        ctxt.stroke();

        // Draw the inner bezier curve
        ctxt.lineCap = opt.cap;
        ctxt.strokeStyle = opt.color;
        ctxt.lineWidth = opt.width;
        ctxt.beginPath();
        ctxt.moveTo(p1[0], p1[1]);
        ctxt.lineTo(p2[0], p2[1]);
        ctxt.stroke();

        /* start drawing arrows */
        var t1 = p1;
        var t2 = p2;

        var z = [0, 0]; //point on the wire with constant distance (dlug) from terminal2
        var dlug = 20; //arrow length
        var t = (distance === 0) ? 0 : 1 - (dlug / distance);
        z[0] = Math.abs(t1[0] + t * (t2[0] - t1[0]));
        z[1] = Math.abs(t1[1] + t * (t2[1] - t1[1]));

        //line which connects the terminals: y=ax+b
        var a, b;
        var W = t1[0] - t2[0];
        var Wa = t1[1] - t2[1];
        var Wb = t1[0] * t2[1] - t1[1] * t2[0];
        if (W !== 0) {
            a = Wa / W;
            b = Wb / W;
        } else {
            a = 0;
        }
        //line perpendicular to the main line: y = aProst*x + b
        var aProst, bProst;
        if (a === 0) {
            aProst = 0;
        } else {
            aProst = -1 / a;
        }
        bProst = z[1] - aProst * z[0]; //point z lays on this line
        //we have to calculate coordinates of 2 points, which lay on perpendicular line and have the same distance (d) from point z
        var A = 1 + Math.pow(aProst, 2);
        var B = 2 * aProst * bProst - 2 * z[0] - 2 * z[1] * aProst;
        var C = -2 * z[1] * bProst + Math.pow(z[0], 2) + Math.pow(z[1], 2) - Math.pow(d, 2) + Math.pow(bProst, 2);
        var delta = Math.pow(B, 2) - 4 * A * C;
        if (delta < 0) {
            return;
        }

        var x1 = (-B + Math.sqrt(delta)) / (2 * A);
        var x2 = (-B - Math.sqrt(delta)) / (2 * A);
        var y1 = aProst * x1 + bProst;
        var y2 = aProst * x2 + bProst;

        if (t1[1] == t2[1]) {
            var o = (t1[0] > t2[0]) ? 1 : -1;
            x1 = t2[0] + o * dlug;
            x2 = x1;
            y1 -= d;
            y2 += d;
        }

        //triangle fill
        ctxt.fillStyle = opt.color;
        ctxt.beginPath();
        ctxt.moveTo(t2[0], t2[1]);
        ctxt.lineTo(x1, y1);
        ctxt.lineTo(x2, y2);
        ctxt.fill();

        //triangle border
        ctxt.strokeStyle = opt.bordercolor;
        ctxt.lineWidth = opt.borderwidth;
        ctxt.beginPath();
        ctxt.moveTo(t2[0], t2[1]);
        ctxt.lineTo(x1, y1);
        ctxt.lineTo(x2, y2);
        ctxt.lineTo(t2[0], t2[1]);
        ctxt.stroke();
    }
};
